定位
定位功能
- 定位主要用于获取用户当前地理位置信息。
- 常用的定位技术:
GPS定位(全球定位系统:最精准的定位方式);
Skyhook Wi-Fi定位(Wi-Fi路由器);
因特网提供商定位技术(提供商中心站);
多种定位方法混合使用; - Core Location是iOS中实现定位功能的框架,提供了大量接口对定位功能进行配置及获取地理位置数据。
- 使用Core Location需要导入框架:CoreLocation.framework。
- CoreLocation提供了CLLocationManager类来对定位功能进行管理,包括定位功能的配置、开始、停止定位等。
- CoreLocation也提供了CLLocationManagerDelegate委托协议来处理CLLocationManager在定位过程中触发的事件。
CLLocationManager 工作流程
- CLLocationManager 定位授权
iOS8以后,如果需要使用定位功能,需请求用户授权,在首次运行时会弹框提示,方法如下:
1 | // 1、请求在使用期间授权定位,需在Info.plist文件中加入字段:NSLocationWhenInUseUsageDescription |
- CLLocationManager 常用属性
1 | delegate:设置代理 |
CLLocationManager 常用方法
类方法
1 | // 1、是否启用定位服务,通常如果用户没有启用定位服务可以提示用户打开定位服务 + (BOOL)locationServicesEnabled; // 2、定位服务授权状态,返回枚举类型: + (CLAuthorizationStatus)authorizationStatus; |
- 实例化方法
1 | // 1、开始定位追踪 |
- 代理方法
1 | // 1、定位失败 - (void)locationManager:(CLLocationManager *)manager |
CLLocationManager 定位代码示例
1 | #import "ViewController.h" |
- 注意:
1 | 1、定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。 |
地理编码
除了提供位置跟踪功能之外,在定位服务中还包含CLGeocoder 类用于处理地理编码和逆地理编码(又叫反地理编码)功能。
地理编码:根据给定的位置(通常是地名)确定地理坐标(经、纬度)。
逆地理编码:可以根据地理坐标(经、纬度)确定位置信息(街道、门牌等)。
- 地理编码方法
1 | // 1、地理编码 |
- 地理编码示例
1 | #import "ViewController.h" |
- 注意:地理编码和逆地理编码不可同时执行;
地图
iOS从6.0开始地图数据不再由谷歌驱动,而是改用自家地图,当然在国内它的数据是由高德地图提供的。这样一来,如果在iOS6.0之前进行地图开发的话使用方法会有所不同,基于目前的情况其实使用iOS6.0之前版本的系统基本已经寥寥无几了,所有在接下来的内容中不会再针对iOS5及之前版本的地图开发进行介绍。
在iOS中进行地图开发主要有两种方式,一种是直接利用MapKit框架进行地图开发,利用这种方式可以对地图进行精准的控制;另一种方式是直接调用苹果官方自带的地图应用,主要用于一些简单的地图应用(例如:进行导航覆盖物填充等),无法进行精确的控制。当然,本节重点内容还是前者,后面的内容也会稍加提示。
Map Kit框架中 MKMapView类 提供了系统自带的地图界面效果,配合Core Location的使用可以展示多样化的信息。
使用Map Kit需要导入框架:MapKit.framework
MKMapView 常用属性
showsUserLocation:设置是否显示用户位置
userTrackingMode:设置跟踪类型,枚举类型
1
2
3
4
5MKUserTrackingModeNone:不进行用户位置跟踪
MKUserTrackingModeFollow:跟踪用户位置
MKUserTrackingModeFollowWithHeading:跟踪用户位置并且跟踪用户前进方向showsTraffic:设置是否显示交通(ios9新特性)
showsScale:设置是否显示比例(ios9新特性)
showsCompass:设置是否显示指南针(ios9新特性)
userLocation:用户位置信息,只读属性
userLocation.title:设置用户位置信息标题
userLocation.subtitle:设置用户位置信息子标题
annotations:当前地图中的所有大头针,只读属性
mapType:设置地图类型
1 | MKMapTypeStandard:标准地图,一般情况下使用此地图即可满足 |
MKMapView 常用方法
- 初始化方法
1 | - (instancetype)initWithFrame:(CGRect)frame; |
- 实例化方法
1 | // 1、添加大头针,对应的有添加大头针数组 |
- 代理方法
1 | // 1、用户位置发生改变时触发(第一次定位到用户位置也会触发该方法) |
用户位置跟踪
在很多带有地图的应用中默认打开地图都会显示用户当前位置,同时将当前位置标记出来放到屏幕中点方便用户对周围情况进行查看。如果在iOS6或者iOS7中实现这个功能只需要添加地图控件、设置用户跟踪模式、在didUpdateUserLocation:代理方法中设置地图中心区域及显示范围。但是在iOS8中用法稍有不同:
由于在地图中进行用户位置跟踪需要使用定位功能,而定位功能在iOS8中设计发生了变化,因此必须按照前面定位章节中提到的内容进行配置和请求。 iOS8中不需要进行中心点的指定,默认会将当前位置设置中心点并自动设置显示区域范围。
了解以上两点,要进行用户位置跟踪其实就相当简单了,值得一提的是didUpdateUserLocation:这个代理方法。这个方法只有在定位到当前位置之后就会调用,以后每当用户位置发生改变就会触发,调用频率相当频繁。
大头针
- 在iOS开发中经常会标记某个位置,需要使用地图标注,也就是大家俗称的“大头针”。只要一个NSObject类实现MKAnnotation协议就可以作为一个大头针,通常会重写协议中coordinate(标记位置)、title(标题)、subtitle(子标题)三个属性,然后在程序中创建大头针对象并调用addAnnotation:方法添加大头针即可(之所以iOS没有定义一个基类实现这个协议供开发者使用,多数原因应该是MKAnnotation是一个模型对象,对于多数应用模型会稍有不同,例如后面的内容中会给大头针模型对象添加其他属性)。下面代码示例中,实现通过长按手势,添加大头针逻辑。
1 | - (void)respondsToGesture:(UILongPressGestureRecognizer *)gesture { // 当长按手势开始时,添加一个标注数据源if (gesture.state == UIGestureRecognizerStateBegan) { // 获取用户长按手势在地图上的点CGPoint point = [gesture locationInView:self.mapView]; // 将地图上的点转化为经纬度 CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; // 创建一个标注数据源,这里使用系统标注数据源:MKPointAnnotation,如果要自定义,必须遵守<MKAnnotation>协议 MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; // 配置标注数据源 annotation.coordinate = coordinate; |
- MKAnnotationView 标注视图
在一些应用中系统默认的大头针样式可能无法满足实际的需求,此时就需要修改大头针视图默认样式。根据前面MapKit的代理方法不难发现viewForAnnotation:方法可以返回一个大头针视图,只要实现这个方法并在这个方法中定义一个大头针视MKAnnotationView对象并设置相关属性就可以改变默认大头针的样式
MKPinAnnotationView
MKPinAnnotationView为MKAnnotationView子类,其特有属性如下:
pinTintColor:设置大头针前景色(iOS9新特性)
animatesDrop:设置大头针凋零效果
MKAnnotationView 常用属性
1
2
3
4
5
6
7image:设置大头针图片
selected:是否被选中状态
annotation:大头针模型信息,包括标题、子标题、地理位置
calloutOffset:点击大头针时弹出详情信息视图的偏移量
leftCalloutAccessoryView:弹出详情左侧视图
rightCalloutAccessoryView:弹出详情右侧视图
canShowCallout:点击大头针是否显示标题、子标题内容等,注意如果在viewForAnnotation:方法中重新定义大头针默认情况是无法交互的,需要设其值为true。注意:
1
2
3
41、这个代理方法的调用时机:每当有大头针显示到系统可视界面中时就会调用此方法返回一个大头针视图放到界面中,同时当前系统位置标注(也就是地图中蓝色的位置点)也是一个大头针,也会调用此方法,因此处理大头针视图时需要区别对待。
2、类似于UITableView的代理方法,此方法调用频繁,开发过程中需要重复利用MapKit的缓存池将大头针视图缓存起来重复利用。
3、自定义大头针默认情况下不允许交互,如果交互需要设置canShowCallout = true。
4、如果代理方法返回nil则会使用默认大头针视图,需要根据情况设置。下面例子进行了标注视图的自定义,这里设置了大头针的弹出视图、大头针颜色以及偏移量等信息。
1 |
|
导航
在自定义标注视图上添加导航按钮(这里需说明:如果添加在标注视图上的控件继承于UIControl,无需添加事件),在点击导航按钮时会自动触发calloutAccessoryControlTapped:方法,如下将实现地图导航路线绘制关键代码。
效果展示
- 代码示例
1 | - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { |
系统自带地图导航
- 要使用地图导航功能在自带地图应用中相当简单,只要设置参数配置导航模式即可。
- 效果展示
- 代码示例
1 |
|
特别说明
- 由于定位和地图框架中用到了诸多类,有些初学者容易混淆,下面简单对比一下。
1 | CLLocation:用于表示位置信息,包含地理坐标、海拔等信息,包含在CoreLoaction框架中。 |